package com.admin_system.controller;

import com.admin_system.service.ExcelTemplateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Excel模板控制器类
 * 该控制器类用于接收前端传来的Excel文件和替换文本请求，
 * 并调用服务层的方法处理数据，最后将处理结果返回给前端。
 */
@RestController
public class ExcelTemplateController {

    private static final Logger logger = LoggerFactory.getLogger(ExcelTemplateController.class);
    
    // 用于标记是否正在导出，保证只有一个用户可以进行导出操作
    private static volatile boolean isExporting = false;

    /**
     * 自动注入ExcelTemplateService服务实例
     */
    @Autowired
    private ExcelTemplateService excelTemplateService;

    /**
     * 处理Excel文件并返回文本结果
     * 该接口用于处理前端的Excel处理请求，并返回处理结果的文本信息。
     *
     * @param file            前端上传的Excel数据文件
     * @param replacementText 用于替换表头括号内文字的文本
     * @return 处理结果的字符串信息，可能包含错误信息
     */
    @PostMapping("/processExcel")
    public String processExcel(@RequestParam("file") MultipartFile file,
                               @RequestParam("replacementText") String replacementText) {
        logger.info("接收到processExcel请求: 文件名={}, 替换文本={}", 
                   file != null ? file.getOriginalFilename() : "null", 
                   replacementText);
        try {
            // 调用服务层的方法处理数据
            return excelTemplateService.processData(file, replacementText);
        } catch (Exception e) {
            logger.error("处理Excel出错: ", e);
            // 若处理过程中出现异常，返回错误信息
            return "错误: " + e.getMessage();
        }
    }
    
    /**
     * 处理Excel文件并直接返回压缩包下载
     * 该接口用于处理前端的Excel文件并生成包含所有班级Excel文件的压缩包，
     * 直接提供给用户下载，无需先保存在服务器。
     *
     * @param file            前端上传的Excel数据文件
     * @param replacementText 用于替换表头括号内文字的文本
     * @param includePdf      是否包含PDF文件
     * @return 包含所有生成Excel文件的压缩包响应
     */
//    @CrossOrigin(origins = "http://10.7.7.149:8080")
    @PostMapping("/downloadExcel")
    public ResponseEntity<?> downloadExcel(@RequestParam("file") MultipartFile file,
                                           @RequestParam("replacementText") String replacementText,
                                           @RequestParam(name = "includePdf", required = false, defaultValue = "false") boolean includePdf) {
        logger.info("接收到downloadExcel请求: 文件名={}, 大小={}字节, 替换文本={}, 是否包含PDF={}", 
                   file != null ? file.getOriginalFilename() : "null",
                   file != null ? file.getSize() : 0,
                   replacementText,
                   includePdf);
        
        // 检查是否有其他用户正在执行导出操作
        if (isExporting) {
            logger.warn("已有其他用户正在使用学号导出工具，请求被拒绝");
            Map<String, Object> response = new HashMap<>();
            response.put("status", "busy");
            response.put("message", "系统正在为其他用户处理导出请求，请稍后再试");
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(response);
        }
        
        if (file == null || file.isEmpty()) {
            logger.error("文件为空或未接收到文件");
            return ResponseEntity.badRequest().body("未接收到有效的Excel文件");
        }
        
        // 设置导出状态为正在导出
        isExporting = true;
        try {
            // 调用服务层处理数据并获取结果，包括压缩包资源和超限班级列表
            Map<String, Object> result = excelTemplateService.processDataAndZipWithOverSizedClasses(file, replacementText, includePdf);
            
            // 获取生成的压缩包资源
            Resource zipResource = (Resource) result.get("resource");
            
            // 获取超过人数限制的班级列表
            @SuppressWarnings("unchecked")
            List<String> overSizedClasses = (List<String>) result.get("overSizedClasses");
            
            // 设置下载文件名，使用replacementText作为基础名称
            String downloadFilename = replacementText + ".zip";
            logger.info("生成文件成功，准备下载: {}, 超限班级数量: {}", downloadFilename, 
                       overSizedClasses != null ? overSizedClasses.size() : 0);
            
            // 设置HTTP响应头，告知浏览器这是一个需要下载的文件
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", downloadFilename);
            
            // 如果有超过人数限制的班级，将其加入到自定义响应头中
            if (overSizedClasses != null && !overSizedClasses.isEmpty()) {
                // 将班级列表格式化为每个班级一条明确的消息
                String[] encodedMessages = new String[overSizedClasses.size()];
                for (int i = 0; i < overSizedClasses.size(); i++) {
                    String originalMessage = overSizedClasses.get(i);
                    try {
                        encodedMessages[i] = URLEncoder.encode(originalMessage, StandardCharsets.UTF_8);
                    } catch (Exception e) {
                        logger.warn("URL编码班级信息时出错: {}", originalMessage, e);
                        encodedMessages[i] = "EncodingError"; 
                    }
                }
                
                String joinedEncodedMessage = String.join("|", encodedMessages);
                headers.add("X-Oversized-Classes", joinedEncodedMessage);
                
                headers.add("Access-Control-Expose-Headers", "X-Oversized-Classes, Content-Disposition");
            }
            
            // 返回带有压缩包数据和适当HTTP头的响应
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(zipResource);
            
        } catch (Exception e) {
            logger.error("处理Excel文件时发生错误: ", e);
            // 发生异常时，返回错误状态
            return ResponseEntity.badRequest().body("处理Excel文件时发生错误: " + e.getMessage());
        } finally {
            // 无论成功还是失败，都需要重置导出状态
            isExporting = false;
            logger.info("导出操作完成，重置导出状态");
        }
    }
}    